-module(recursion).
-export([factorial/1, fib/1, pieces/1, perfect/1]).


% tail-recursive version
factorial(N) when N > 0 ->
    factorial_iter(1, N).

factorial_iter(Result, 0) ->
    Result;
factorial_iter(IntermediateResult, N) ->
    factorial_iter(IntermediateResult * N, N - 1).


% 1 1 2 3 5 8 13 21 34 55 89
fib(N) ->
    fib_iter(0, 1, N).

fib_iter(_PrevPrev, Prev, 0) ->
    Prev;
fib_iter(PrevPrev, Prev, N)->
    fib_iter(Prev, PrevPrev + Prev, N - 1).


% 1 2 4 7 11 16 22 29
pieces(Cuts) ->
    ((Cuts * (Cuts + 1)) / 2) + 1.


% A perfect number is a number, which is the sum of its divisors.
perfect(N) ->
    perfect_iter(1, 0, N).

perfect_iter(_Addend, Sum, N) when Sum == N ->
    true;
perfect_iter(_Addend, Sum, N) when Sum > N ->
    false;
perfect_iter(Addend, Sum, N) when N rem Addend == 0 ->
    perfect_iter(Addend + 1, Sum + Addend, N);
perfect_iter(Addend, Sum, N) when N rem Addend =/= 0 ->
    perfect_iter(Addend + 1, Sum, N).
